﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team - cellcloudproject@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellDate_h
#define CellDate_h

#include "CellPrerequisites.h"

namespace cell
{
/** \addtogroup Core
 *  @{
 */
/** \addtogroup Util
 *  @{
 */

/** 时间间隔描述类。
@author
	Jiangwei Xu
*/
class _CellExport TimeDuration : public GeneralAlloc
{
public:
	/** 构造函数。
	*/
	TimeDuration(void);

	/** 析构函数。
	*/
	virtual ~TimeDuration(void);

protected:
	/**
	*/
	TimeDuration(const uint64 numOfDuration, const int unit);

public:
	/** 时间间隔单位。
	*/
	typedef enum _DurationUnit
	{
		YEAR = 1,
		MONTH,
		WEEK,
		HOUR,
		MINUTE,
		SECOND,
		MILLISECOND
	} DurationUnit;

public:
	/** 赋值操作。
	*/
	TimeDuration& operator=(const TimeDuration& duration);

public:
	/** 以年为单位设置时间间隔。
	*/
	static TimeDuration years(int numOfYeas);
	/** 以月为单位设置时间间隔。
	*/
	static TimeDuration months(int numOfMonths);
	/** 以周为单位设置时间间隔。
	*/
	static TimeDuration weeks(int numOfWeeks);
	/** 以天为单位设置时间间隔。
	*/
	static TimeDuration days(int numOfDays);
	/** 以小时为单位设置时间间隔。
	*/
	static TimeDuration hours(long numOfHours);
	/** 以分钟为单位设置时间间隔。
	*/
	static TimeDuration minutes(long numOfMinutes);
	/** 以秒为单位设置时间间隔。
	*/
	static TimeDuration seconds(long numOfSeconds);
	/** 以毫秒为单位设置时间间隔。
	*/
	static TimeDuration milliseconds(long numOfMilliseconds);

private:
	uint64 mNumOfDuration;
	int mUnit;

	friend class Date;
};

/** 日期与时间工具类。
@author
	Jiangwei Xu
*/
class _CellExport Date : public GeneralAlloc
{
public:
	/**
	*/
	Date(void);

	/**
	*/
	Date(uint64 absoluteTime);

	/**
	*/
	Date(uint16 year, uint16 month, uint16 date);

	/**
	*/
	Date(uint16 year, uint16 month, uint16 date, uint16 hours, uint16 minutes, uint16 seconds, uint16 milliseconds = 0);

	/**
	*/
	virtual ~Date(void);

public:
	/**
	*/
	uint64 getTime(void);
	/**
	*/
	uint64 getTime(void) const;

	/** Returns the full year (a four-digit number, such as 2000) of a Date object according to local time.
	*/
	uint16 getYear(void);
	uint16 getYear(void) const;

	/** Returns the month (1 for January, 2 for February, and so on) portion of this Date according to local time.
	*/
	uint16 getMonth(void);
	uint16 getMonth(void) const;

	/** Returns the day of the month (an integer from 1 to 31) specified by a Date object according to local time.
	*/
	uint16 getDate(void);
	uint16 getDate(void) const;

	/** Returns the day of the week (0 for Sunday, 1 for Monday, and so on) specified by this Date according to local time.
	*/
	uint16 getDay(void);
	uint16 getDay(void) const;

	/** Returns the hour (an integer from 0 to 23) of the day portion of a Date object according to local time.
	*/
	uint16 getHours(void);
	uint16 getHours(void) const;

	/** Returns the minutes (an integer from 0 to 59) portion of a Date object according to local time.
	*/
	uint16 getMinutes(void);
	uint16 getMinutes(void) const;

	/** Returns the seconds (an integer from 0 to 59) portion of a Date object according to local time.
	*/
	uint16 getSeconds(void);
	uint16 getSeconds(void) const;

	/** Returns the milliseconds (an integer from 0 to 999) portion of a Date object according to local time.
	*/
	uint16 getMilliseconds(void);
	uint16 getMilliseconds(void) const;

	/** Returns the milliseconds (a long integer from 0 to 999999) portion of a Date object according to local time.
	*/
	ulong getMicroseconds(void);
	ulong getMicroseconds(void) const;

	/**
	*/
	void setTime(uint64 time);

public:
	/**
	*/
	Date& operator=(const Date& date);
	/**
	*/
	bool operator<(const Date& date) const;
	/**
	*/
	bool operator>(const Date& date) const;
	/**
	*/
	bool operator==(const Date& date) const;
	/**
	*/
	bool operator!=(const Date& date) const;
	/**
	*/
	bool operator<=(const Date& date) const;
	/**
	*/
	bool operator>=(const Date& date) const;

	/**
	*/
	Date operator+(const TimeDuration& duration) const;
	/**
	*/
	Date operator-(const TimeDuration& duration) const;
	/**
	*/
	Date operator+(const uint64 timeDurationInMilliseconds) const;
	/**
	*/
	Date operator-(const uint64 timeDurationInMilliseconds) const;

	/**
	*/
	Date& operator+=(const TimeDuration& duration);
	/**
	*/
	Date& operator-=(const TimeDuration& duration);
	/**
	*/
	Date& operator+=(const uint64 timeDurationInMilliseconds);
	/**
	*/
	Date& operator-=(const uint64 timeDurationInMilliseconds);

public:
	static const boost::posix_time::time_duration TZ_EA8;

	/** YYYY-mm-DD HH:MM:SS.fff
	*/
	static String convertDateToString(const Date& date, bool msec = false);

	/** YYYY-mm-DD HH:MM:SS.fff
	*/
	static Date convertStringToDate(const String& date);

	/** 将 std::time_t 转为 Date 型。
	*/
	static Date convertTimeToDate(std::time_t& time);

	/** 将 std::tm 转为 Date 型。
	*/
	static Date convertTimeToDate(std::tm& time);

private:
	uint64 mTimestamp;
	boost::posix_time::ptime mTime;
};

/** @} */
/** @} */
} // end namespace cell

#endif // CellDate_h
